package naga.x.proxy;

import java.net.SocketAddress;
import java.util.Collection;
import java.util.concurrent.TimeUnit;

import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;

import com.alibaba.fastjson.JSON;

import naga.x.App;
import naga.x.net.Packet;
import naga.x.net.PacketHandler;
import naga.x.net.Session;
import naga.x.net.impl.pomelo.PomeloClientSessionService;
import naga.x.net.impl.pomelo.PomeloPacket;
import naga.x.net.impl.pomelo.packet.ByteArrayPacket;
import naga.x.net.proxy.ProxyOpCode;
import naga.x.net.proxy.ProxyPacket;
import naga.x.util.IOUtils;
import naga.x.util.SessionUtils;
import naga.x.util.StringUtils;

/**
 * 客户端与代理服连接Service
 * @author yang.li
 *
 */
public class ProxyPomeloClientSessionService extends PomeloClientSessionService implements PacketHandler {

	private GameServerConnector conn;
	
	public ProxyPomeloClientSessionService() {
		conn = App.getApp().getServiceManager().get(GameServerConnector.class);
		App.getApp().getSchedule().scheduleAtFixedRate(new Runnable() {
			@Override
			public void run() {
				LOG.info("[SESSIONS]" + sessions.size());
			}
		}, 0, 60, TimeUnit.SECONDS);
	}
	
	@Override
	public String getId() {
		return "PROXY";
	}

	@Override
	public void sessionCreated(IoSession session) throws Exception {
		if (conn.isConnected()) {
			Session sess = new ClientSession(session, this, this);
			session.setAttribute(SessionUtils.GAME_SESSION, sess);
//			sessions.put(sess.getId(), sess);
//			App.getApp().getEventManager().addEvent(Events.EVENT_SESSION_CREATED, sess);
			SocketAddress addr = session.getRemoteAddress();
			// 同步客户端ip给游戏服务器
			ProxyPacket p = new ProxyPacket(ProxyOpCode.SYNC_CLIENT_IP, IoBuffer.wrap(StringUtils.stringToBytes(String.valueOf(addr), IOUtils.UTF8)), (int) sess.getId(), -1, (byte) 0);
			conn.send(p);
			fireSessionCreated(sess);
//			LOG.info("[{}]SESSION CREATED[{}]{}", getId(), addr, sess.getId());
		} else {
			session.closeOnFlush();
		}
	}

	@Override
	public void sessionClosed(IoSession session) throws Exception {
		Session sess = (Session) session.getAttribute(SessionUtils.GAME_SESSION);
		if (sess != null) {
			// 通知游戏服关闭这个客户端连接
			ProxyPacket p = new ProxyPacket(ProxyOpCode.SESSION_CLOSE, null, (int) sess.getId(), -1, (byte) 0);
			conn.send(p);
			super.sessionClosed(session);
		}
	}
	
	/**
	 * 转发来自游戏服的数据包给客户端
	 * @param proxyPacket
	 */
	public void dispatch(ProxyPacket proxyPacket) {
		if (proxyPacket.getOpCode() == ProxyOpCode.BROADCAST) {
			ByteArrayPacket packet = new ByteArrayPacket(proxyPacket.getDataAsByteArray());
			Collection<Session> vals = sessions.values();
			for (Session sess : vals) {
				sess.send(packet);
			}
			return;
		}
		Session sess = getSession(proxyPacket.getSessionId());
		if (sess == null) {
			return;
		}
		if (proxyPacket.getOpCode() == ProxyOpCode.SESSION_CLOSE) {
			sess.close(false);
		} else {
			ByteArrayPacket packet = new ByteArrayPacket(proxyPacket.getDataAsByteArray());
			sess.send(packet);
		}
	}
	
	public Session getSession(long id) {
		return sessions.get(id);
	}

	@Override
	public void handle(Session session, Packet packet) {
		PomeloPacket pp = (PomeloPacket) packet;
		IoBuffer data;
		if (pp instanceof ByteArrayPacket) {
			data = IoBuffer.wrap(((ByteArrayPacket) pp).toByteArray());
		} else {
			data = IoBuffer.wrap(JSON.toJSONBytes(pp));
		}
		// 转发给游戏服
		ProxyPacket proxyPacket = new ProxyPacket(pp.getOpCode(), data, (int) session.getId(), pp.getSerial(), pp.getPackageType());
		conn.send(proxyPacket);
	}
	
}
